Skip to content

[FEAT] 에러/로딩/온보딩 상태 페이지 Lottie 애니메이션 적용#131

Merged
kimminna merged 7 commits into
developfrom
feat/web/130-status-screen-lottie
Jul 10, 2026
Merged

[FEAT] 에러/로딩/온보딩 상태 페이지 Lottie 애니메이션 적용#131
kimminna merged 7 commits into
developfrom
feat/web/130-status-screen-lottie

Conversation

@kimminna

@kimminna kimminna commented Jul 9, 2026

Copy link
Copy Markdown
Member

ISSUE 🔗

close #130



What is this PR? 🔍

전역 에러(500), 404, 로딩, 온보딩 화면에 공통 StatusScreen/LottiePlayer 컴포넌트를 도입해 Lottie 애니메이션 기반 상태 화면으로 정비했습니다.

배경

  • 기존 구조: global-error.tsx만 최소한으로 존재했고, 404·500 전용 페이지와 로딩 화면은 없었으며 상태별 안내 문구도 별도로 관리되지 않았습니다.
  • 발생 문제: 에러 발생 시 사용자에게 상황(일시 장애/존재하지 않는 페이지/전역 크래시)에 맞는 안내를 주지 못했고, 페이지 전환 로딩 중에도 빈 화면이 노출됐습니다.
  • 해결 방향: 상태 화면 전용 공통 컴포넌트(StatusScreen)와 Lottie 렌더러(LottiePlayer)를 만들고, 각 상태(500/404/전역 에러/로딩/온보딩)마다 해당 Lottie 애니메이션과 i18n 문구를 매핑했습니다.

LottiePlayer / StatusScreen 공통 컴포넌트

  • 변경 요약: lottie-react 기반 LottiePlayer와, 타이틀·설명·액션 버튼을 배치하는 StatusScreen을 새로 추가했습니다.
  • 이유: 404/500/전역 에러 화면이 레이아웃(Lottie + 타이틀 + 설명 + 홈 버튼)을 동일하게 공유해 매번 마크업을 반복할 필요가 없었습니다.
  • 구현 방식: LottiePlayersrc로 받은 경로를 fetch해 JSON 애니메이션 데이터를 상태로 들고 있다가 로드되면 Lottie 컴포넌트를 렌더링합니다. 로드 실패 시에는 컨테이너만 비워 두어 레이아웃 시프트를 방지합니다. StatusScreenlottieSrc/title/description/action을 props로 받아 중앙 정렬 레이아웃을 구성합니다.

상태 페이지 (500 / 404 / 전역 에러 / 로딩)

  • 변경 요약: [locale]/error.tsx(500), [locale]/not-found.tsx(404), global-error.tsx(전역 크래시), [locale]/loading.tsx를 새로 추가/정비하고, 404 유도를 위한 [locale]/[...rest] catch-all 라우트를 추가했습니다.
  • 이유: Next.js App Router 컨벤션상 각 상태를 별도 파일로 분리해야 해당 상태에서만 렌더링되며, catch-all 라우트가 없으면 정의되지 않은 경로가 404로 떨어지지 않습니다.
  • 구현 방식: 각 페이지는 StatusScreen에 상태별 lottieSrc(/lottie/500.json, 404.json, error.json)와 홈으로 이동하는 action을 전달합니다. loading.tsx는 텍스트 없이 LottiePlayer만 화면 중앙에 배치했습니다. global-error.tsx<html>/<body>를 직접 렌더링해야 하는 Next.js 제약 때문에 NextIntlClientProvider로 메시지를 직접 주입하고, 최초 렌더 시 URL 세그먼트에서 locale을 추출해 폰트·언어를 맞췄습니다. 또한 500/404/전역 에러 화면이 각각 별도로 정의된 Error/NotFound/GlobalError 번역 네임스페이스 대신 전부 Error를 참조하고 있던 것을 발견해, 상태별로 올바른 네임스페이스를 참조하도록 수정했습니다.
  • 경계 · 제약: global-error.tsx는 클라이언트 컴포넌트로 유지되며 Sentry.captureException으로 에러를 보고합니다.

온보딩 페이지

  • 변경 요약: 온보딩 페이지에 LottiePlayer로 온보딩 애니메이션(/lottie/onboarding.json)을 노출했습니다.
  • 이유: 기존에는 빈 페이지였고, 같은 Lottie 도입 작업에서 함께 준비된 에셋을 반영했습니다.
  • 구현 방식: 화면 좌측에 고정 위치(top-1/2 left-[197px])로 애니메이션을 배치했습니다.



To Reviewers

  • global-error.tsx는 Next.js 특성상 <html>/<body>를 직접 감싸고 locale을 클라이언트에서 뒤늦게 결정하는 구조라 최초 렌더에는 기본 locale(routing.defaultLocale)로 잠깐 보였다가 바뀝니다. 이 전제가 맞는지 확인 부탁드립니다.
  • 온보딩 페이지 변경은 이슈 [FEAT] 에러/로딩 상태 페이지 Lottie 애니메이션 적용 #130(에러/로딩 상태 페이지) 범위와는 결이 다르지만, 같은 Lottie 에셋 작업 세션에서 나온 변경이라 같은 브랜치에 포함했습니다. 별도 이슈로 분리가 필요하면 말씀해 주세요.
  • 이번 세션에서는 브라우저로 직접 화면을 띄워보지 못해 실제 렌더링 스크린샷은 없습니다. 병합 전에 404/500/로딩/온보딩 화면을 한 번씩 확인해 주시면 좋겠습니다.



Screenshot 📷



Test Checklist ✔

  • pnpm check-types 통과
  • pnpm lint 통과
  • 404/500/전역 에러/로딩/온보딩 화면 브라우저 확인 — 미실행: 리뷰 시 확인 필요

kimminna added 3 commits July 10, 2026 00:17
- 상태 페이지 애니메이션 렌더링을 위해 lottie-react 패키지를 추가했습니다
- 공통 LottiePlayer, StatusScreen 컴포넌트를 추가했습니다
- global-error, 500, 404 페이지에 상태별 Lottie 애니메이션과 안내 문구를 적용했습니다
- loading 페이지를 로띠 애니메이션만 중앙에 노출하도록 구성했습니다
- 404 응답을 유도하기 위한 [...rest] catch-all 라우트를 추가했습니다
- 500/404/전역 에러 문구가 각각 올바른 번역 네임스페이스를 참조하도록 수정했습니다
- 온보딩 페이지에 LottiePlayer로 온보딩 애니메이션을 노출했습니다
@vercel

vercel Bot commented Jul 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
timo Ready Ready Preview, Comment Jul 10, 2026 5:28pm

@github-actions github-actions Bot requested review from ehye1 and jjangminii July 9, 2026 15:22
@github-actions github-actions Bot added ⏰ Timo-web Timo 웹 서비스 ✨ Feature 새로운 기능(기능성) 구현 ♦️ 민아 민아상 labels Jul 9, 2026
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@kimminna, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 55 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4308695e-9328-4b76-bcff-4345bfff74c1

📥 Commits

Reviewing files that changed from the base of the PR and between ba898b0 and c0fb743.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • apps/timo-web/messages/en.json
  • apps/timo-web/messages/ko.json
  • apps/timo-web/package.json

Walkthrough

전역 에러, 500 에러, 404, 로딩, 온보딩, 캐치올 라우트에 공통 LottiePlayerStatusScreen 기반 UI를 추가했습니다. 관련 번역 키, lottie-react 의존성, 500 상태용 Lottie 애셋도 포함됩니다.

Changes

상태 페이지 Lottie 적용

Layer / File(s) Summary
LottiePlayer 공통 컴포넌트
apps/timo-web/components/lottie/LottiePlayer.tsx, apps/timo-web/package.json
Lottie JSON 비동기 로드, 요청 취소, 접근성 속성, 조건부 렌더링을 지원하는 컴포넌트와 lottie-react 의존성을 추가했습니다.
StatusScreen 공통 컴포넌트
apps/timo-web/components/status-screen/StatusScreen.tsx
Lottie, 제목, 설명, 선택적 액션을 중앙 정렬 상태 화면으로 렌더링하는 컴포넌트를 추가했습니다.
전역 에러 페이지 리뉴얼
apps/timo-web/app/global-error.tsx
경로 기반 로케일·메시지 선택과 번역 기반 StatusScreen 렌더링을 추가하고 Sentry 예외 캡처를 유지했습니다.
500 에러 페이지
apps/timo-web/app/[locale]/error.tsx
번역된 에러 문구, 500 Lottie, Sentry 캡처, 홈 링크를 사용하는 에러 페이지를 추가했습니다.
404 페이지 및 캐치올 라우트
apps/timo-web/app/[locale]/not-found.tsx, apps/timo-web/app/[locale]/[...rest]/page.tsx
번역된 404 화면과 항상 notFound()를 호출하는 catch-all 라우트를 추가했습니다.
로딩/온보딩 Lottie 적용
apps/timo-web/app/[locale]/loading.tsx, apps/timo-web/app/[locale]/onboarding/page.tsx
로딩 화면에 애니메이션을 추가하고 온보딩 페이지가 Lottie를 표시하도록 변경했습니다.
번역 리소스 및 Lottie 애셋
apps/timo-web/messages/en.json, apps/timo-web/messages/ko.json, apps/timo-web/public/lottie/error.json
Error, NotFound, GlobalError 번역 키와 500 상태용 Lottie JSON을 추가했습니다.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant 방문자
  participant ErrorPage
  participant Sentry
  participant StatusScreen
  participant LottiePlayer

  방문자->>ErrorPage: 라우트 에러 발생
  ErrorPage->>Sentry: captureException(error)
  ErrorPage->>StatusScreen: 번역 문구와 Lottie 경로 전달
  StatusScreen->>LottiePlayer: lottieSrc와 ariaLabel 전달
  LottiePlayer->>LottiePlayer: fetch(src)로 JSON 로드
  LottiePlayer-->>StatusScreen: animationData 렌더링
  StatusScreen-->>방문자: 상태 화면과 홈 액션 표시
Loading

Possibly related PRs

Suggested labels: ♥️ 혜원

Suggested reviewers: ehye1, yumin-kim2

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning 온보딩 페이지 변경은 #130의 에러/로딩 상태 페이지 범위를 벗어난 별도 작업입니다. 온보딩 변경은 별도 이슈로 분리해 제출하고, #130 범위에는 에러·404·로딩·전역 에러 관련 변경만 남겨 주세요.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 상태 페이지에 Lottie 애니메이션을 적용한 핵심 변경을 잘 요약합니다.
Description check ✅ Passed 설명이 공통 컴포넌트 도입과 상태 페이지 정비라는 변경 사항과 잘 맞습니다.
Linked Issues check ✅ Passed #130의 요구사항인 공통 컴포넌트, 전역 에러/Sentry, 404·로딩·catch-all, 번역, lottie-react 추가가 모두 반영되었습니다.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/web/130-status-screen-lottie

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

Storybook Preview

항목 링크
Storybook 열기
Chromatic 빌드 확인

마지막 업데이트: 2026-07-10 17:28 UTC

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

Timo Performance Report

Bundle Size — timo-web
라우트 크기 First Load JS
/[locale]/home 71.44 kB 🟡 277.25 kB
/[locale]/today 52.50 kB 🟡 258.31 kB
/[locale]/focus 51.65 kB 🟡 257.46 kB
/[locale]/settings/account 0 B 🟡 205.81 kB
/[locale]/settings 0 B 🟡 205.81 kB
/[locale]/settings/policy 0 B 🟡 205.81 kB
/[locale]/statistics 49.60 kB 🟡 255.41 kB
/[locale]/[...rest] 0 B 🟡 205.81 kB
/[locale]/onboarding 107.39 kB 🟡 313.20 kB
/[locale] 0 B 🟡 205.81 kB

공유 번들: 205.81 kB
🟢 < 200kB  |  🟡 < 350kB  |  🔴 ≥ 350kB (First Load JS · gzip)

Lighthouse — timo-web
URL Perf A11y LCP CLS TBT
/en/home 🔴 68 🟢 96 🔴 14.0s 🟢 0.000 🟡 324ms
/en/today 🟡 70 🟢 96 🔴 13.7s 🟢 0.000 🟡 256ms
/en/focus 🟡 73 🟡 91 🔴 13.7s 🟢 0.000 🟢 177ms
/en/statistics 🟡 70 🟢 95 🔴 13.7s 🟢 0.000 🟡 272ms

Perf ≥ 70 / A11y ≥ 85 목표
LCP 🟢 < 2.5s 🟡 < 4s 🔴 ≥ 4s  |  CLS 🟢 < 0.1 🟡 < 0.25 🔴 ≥ 0.25  |  TBT 🟢 < 200ms 🟡 < 600ms 🔴 ≥ 600ms

Image Optimization — timo-web

public/ 디렉토리에 이미지가 없습니다.

측정 커밋: 2ddb523

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/timo-web/app/`[locale]/loading.tsx:
- Around line 5-7: `LottiePlayer` is rendered without an accessible name, so
update the loading UI in the `loading.tsx` component to pass a meaningful
`ariaLabel` alongside the existing `src` and `className` props. Use the
`LottiePlayer` usage in this screen to ensure it still renders as `role="img"`
but now has a screen-reader-friendly label that describes the loading state.

In `@apps/timo-web/app/`[locale]/onboarding/page.tsx:
- Around line 5-9: The onboarding page animation in the LottiePlayer usage is
hard-coded for desktop and overflows on small screens, and it also lacks an
accessibility decision. Update the LottiePlayer configuration to use responsive
positioning/sizing in the onboarding page component (for example by adjusting
the current absolute placement across breakpoints or making the desktop-only
intent explicit), and add an appropriate ariaLabel if the animation conveys
meaning or hide it from assistive tech if it is decorative.

In `@apps/timo-web/app/global-error.tsx`:
- Around line 50-58: 중복된 상태 화면 액션 버튼(Link) 구현을 공통 컴포넌트로 추출하세요. global-error.tsx의
action, error.tsx의 action, not-found.tsx의 버튼이 동일한 스타일과 거의 같은 구조를 반복하므로,
StatusActionButton 같은 재사용 컴포넌트를 만들어 href와 label만 받도록 정리하고 세 파일에서 이를 사용하세요. 또한
global-error.tsx와 error.tsx의 wrapping div와 not-found.tsx의 단일 Link 구조 차이를 함께 정리해,
각 화면의 action 렌더링 형태가 일관되게 맞도록 수정하세요.

In `@apps/timo-web/components/lottie/LottiePlayer.tsx`:
- Around line 22-33: In LottiePlayer’s fetch effect, the current response
handling passes every resolved fetch directly to response.json(), which allows
404/500 responses to be treated as valid animation data. Update the useEffect
flow to check response.ok before parsing, and throw an error when it is false so
the failure is routed into the existing catch path. Keep the fix localized to
the fetch chain in LottiePlayer so only valid animation JSON reaches
setAnimationData.

In `@apps/timo-web/messages/ko.json`:
- Around line 44-57: Fix the Korean localization text in ko.json by correcting
the typos in Error.description (“잠시후” to “잠시 후” and “주새요” to “주세요”) and making
punctuation consistent by adding a period to NotFound.description; update the
affected entries in the Error and NotFound message objects so the wording and
sentence endings match the rest of the translations.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 802cb16c-4a85-4edd-b90e-0e30c119f8d0

📥 Commits

Reviewing files that changed from the base of the PR and between 6e082b2 and 5ee988e.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (16)
  • apps/timo-web/app/[locale]/[...rest]/page.tsx
  • apps/timo-web/app/[locale]/error.tsx
  • apps/timo-web/app/[locale]/loading.tsx
  • apps/timo-web/app/[locale]/not-found.tsx
  • apps/timo-web/app/[locale]/onboarding/page.tsx
  • apps/timo-web/app/global-error.tsx
  • apps/timo-web/components/lottie/LottiePlayer.tsx
  • apps/timo-web/components/status-screen/StatusScreen.tsx
  • apps/timo-web/messages/en.json
  • apps/timo-web/messages/ko.json
  • apps/timo-web/package.json
  • apps/timo-web/public/lottie/404.json
  • apps/timo-web/public/lottie/500.json
  • apps/timo-web/public/lottie/error.json
  • apps/timo-web/public/lottie/loading.json
  • apps/timo-web/public/lottie/onboarding.json

Comment thread apps/timo-web/app/[locale]/loading.tsx
Comment on lines +5 to +9
<div className="relative h-screen w-full">
<LottiePlayer
src="/lottie/onboarding.json"
className="absolute top-1/2 left-[197px] w-[500px] -translate-y-1/2"
/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 온보딩 페이지가 데스크톱 전용인지, 반응형 대응이 필요한지 확인합니다.
# 1. 미디어 쿼리나 반응형 클래스 사용 여부 검색
rg -n 'md:|lg:|sm:|xl:' apps/timo-web/app/[locale]/onboarding/

# 2. 다른 페이지의 반응형 패턴 확인
rg -n 'left-\[|w-\[500' apps/timo-web/app/ --type=ts

# 3. Viewport meta 태그 또는 반응형 설정 확인
rg -n 'viewport|max-width|min-width' apps/timo-web/app/[locale]/layout.tsx

Repository: Team-Timo/Timo-client

Length of output: 285


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- onboarding page ---'
sed -n '1,200p' apps/timo-web/app/[locale]/onboarding/page.tsx | cat -n

echo
echo '--- find LottiePlayer definition/usages ---'
fd -a 'LottiePlayer' apps/timo-web components | sed -n '1,120p' || true
rg -n "export .*LottiePlayer|function LottiePlayer|const LottiePlayer|ariaLabel|aria-label" apps/timo-web components -g '!**/node_modules/**' | sed -n '1,200p' || true

echo
echo '--- list lottie component files ---'
fd -a '' components/lottie apps/timo-web/components/lottie 2>/dev/null | sed -n '1,200p' || true

Repository: Team-Timo/Timo-client

Length of output: 1763


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- onboarding-related files ---'
fd -a 'onboarding' apps/timo-web | sed -n '1,200p'

echo
echo '--- onboarding page references ---'
rg -n "onboarding" apps/timo-web -g '!**/node_modules/**' | sed -n '1,200p'

echo
echo '--- LottiePlayer definition ---'
sed -n '1,220p' apps/timo-web/components/lottie/LottiePlayer.tsx | cat -n

echo
echo '--- relevant layout/page sizing hints ---'
sed -n '1,220p' apps/timo-web/app/[locale]/layout.tsx | cat -n

Repository: Team-Timo/Timo-client

Length of output: 3587


온보딩 애니메이션에 반응형/접근성 레일을 깔아주세요
레이아웃 뼈대는 깔끔합니다. 다만 left-[197px] + w-[500px] 조합은 375px 폭에서 오른쪽으로 크게 넘쳐 보입니다. sm/md에서 위치·크기를 조정하거나, 정말 데스크톱 전용이면 의도를 코드에 드러내 주세요.
또한 LottiePlayerariaLabel을 지원하므로, 의미 있는 안내라면 라벨을 넣고 장식용이라면 숨김 처리하는 쪽이 맞습니다.
참고: MDN ARIA, Next.js Accessibility

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/timo-web/app/`[locale]/onboarding/page.tsx around lines 5 - 9, The
onboarding page animation in the LottiePlayer usage is hard-coded for desktop
and overflows on small screens, and it also lacks an accessibility decision.
Update the LottiePlayer configuration to use responsive positioning/sizing in
the onboarding page component (for example by adjusting the current absolute
placement across breakpoints or making the desktop-only intent explicit), and
add an appropriate ariaLabel if the animation conveys meaning or hide it from
assistive tech if it is decorative.

Comment on lines +50 to +58
action={
<div className="flex items-center gap-3">
<Link
href="/"
className="typo-headline-m-16 rounded-[8px] border border-gray-500 px-4 py-2.5 text-gray-900"
>
{t("homeButton")}
</Link>
</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

액션 버튼 코드 중복 — 공통 컴포넌트 추출을 제안합니다.

global-error.tsx, error.tsx(26-34행), not-found.tsx(14-21행) 세 파일에서 동일한 Link 버튼(typo-headline-m-16 rounded-[8px] border border-gray-500 px-4 py-2.5 text-gray-900)이 반복됩니다. not-found.tsx는 wrapping <div> 없이 Link만 전달하고, 나머지 두 파일은 <div className="flex items-center gap-3">으로 감싸고 있어 구조 불일치도 있습니다.

공통 StatusActionButton 컴포넌트를 추출하면 중복 제거와 일관성 확보를 동시에 잡을 수 있습니다.

♻️ 공통 StatusActionButton 컴포넌트 추출 제안
// components/status-screen/StatusActionButton.tsx
import { Link } from "`@/i18n/navigation`";

interface StatusActionButtonProps {
  label: string;
  href?: string;
}

export const StatusActionButton = ({
  label,
  href = "/",
}: StatusActionButtonProps) => (
  <Link
    href={href}
    className="typo-headline-m-16 rounded-[8px] border border-gray-500 px-4 py-2.5 text-gray-900"
  >
    {label}
  </Link>
);

각 파일에서의 사용:

- action={
-   <div className="flex items-center gap-3">
-     <Link
-       href="/"
-       className="typo-headline-m-16 rounded-[8px] border border-gray-500 px-4 py-2.5 text-gray-900"
-     >
-       {t("homeButton")}
-     </Link>
-   </div>
- }
+ action={<StatusActionButton label={t("homeButton")} />}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/timo-web/app/global-error.tsx` around lines 50 - 58, 중복된 상태 화면 액션
버튼(Link) 구현을 공통 컴포넌트로 추출하세요. global-error.tsx의 action, error.tsx의 action,
not-found.tsx의 버튼이 동일한 스타일과 거의 같은 구조를 반복하므로, StatusActionButton 같은 재사용 컴포넌트를 만들어
href와 label만 받도록 정리하고 세 파일에서 이를 사용하세요. 또한 global-error.tsx와 error.tsx의 wrapping
div와 not-found.tsx의 단일 Link 구조 차이를 함께 정리해, 각 화면의 action 렌더링 형태가 일관되게 맞도록 수정하세요.

Comment thread apps/timo-web/components/lottie/LottiePlayer.tsx
Comment thread apps/timo-web/messages/ko.json
@kimminna kimminna changed the title [FEAT] 에러/로딩 상태 페이지 Lottie 애니메이션 적용 [FEAT] 에러/로딩/온보딩 상태 페이지 Lottie 애니메이션 적용 Jul 9, 2026

@ehye1 ehye1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

로띠 파일 어떻게 넣는지 궁금했는데 pr설명이랑 코드 보고 배워갑니다💥
수고하셨습니다!!!💨🫡

useEffect(() => {
const controller = new AbortController();

fetch(src, { signal: controller.signal })

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lottie json 파일을 어떻게 가져오나 궁금했는데 fetch로 가져오게 되면 필요할 때만 가져올 수 있어서 번들 크기를 줄일 수 있겠네요!

.then((response) => response.json())
.then(setAnimationData)
.catch(() => {
// 애니메이션 로드 실패 시 컨테이너만 비운 상태로 유지 (레이아웃 시프트 방지)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lottie 파일이 렌더링 되기 전까지 CLS가 발생하는 것 같은데 나중에 높이 고정해놓거나 placeholder 설정해두면 좋을 것 같아요!

@jjangminii jjangminii left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이제 500,404에러도 이쁘겠네요~
간단한 코멘트라 어푸 먼저 해드릴게요-! 코멘트 내용 확인해주세요!

Comment thread apps/timo-web/messages/ko.json Outdated
},
"Error": {
"title": "잠시 문제가 발생했어요.",
"description": "더 나은 경험을 위해 잠시 점검 중입니다. 잠시후 다시 이용해 주새요.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ㅎㅎㅎㅎㅎ 오타 확인해주세요~

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

허걱~~~

Comment thread apps/timo-web/app/[locale]/loading.tsx Outdated
export default function Loading() {
return (
<div className="flex min-h-screen w-full items-center justify-center">
<LottiePlayer src="/lottie/loading.json" className="w-[143px]" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기 ariaLabel 누락 되었어요~

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

추가했습니다!

Comment on lines +25 to +29
fetch(src, { signal: controller.signal })
.then((response) => response.json())
.then(setAnimationData)
.catch(() => {
// 애니메이션 로드 실패 시 컨테이너만 비운 상태로 유지 (레이아웃 시프트 방지)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fetch(src, { signal: controller.signal })
.then((response) => response.json())
.then(setAnimationData)
.catch(() => {
// 애니메이션 로드 실패 시 컨테이너만 비운 상태로 유지 (레이아웃 시프트 방지)
fetch(src, { signal: controller.signal })
.then((response) => {
if (!response.ok) throw new Error(`Failed to load: ${response.status}`);
return response.json();
})
.then(setAnimationData)
.catch(() => {
// 애니메이션 로드 실패 시 컨테이너만 비운 상태로 유지 (레이아웃 시프트 방지)
});

fetch는 404/500에서도 성공으로 resolve되기 때문에, response.ok 체크 없이 바로 .json()을 호출하면 에러 페이지의 HTML이 animationData로 들어가서 Lottie가 깨질 수 있을 것 같아요!
response.ok가 false일 때 에러를 throw하면 기존 .catch(() => {}) 블록으로 떨어져서 animationData가 null인 상태로 유지되고, Lottie 컴포넌트가 렌더링되지 않아요. 기존 catch 로직을 재활용하면서 최소한의 변경으로 방어할 수 있을 것 같아요!
민아님은 어떻게 생각하시나요?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

response.ok가 false면 에러를 던져서 기존 .catch(() => {})가 그대로 잡아주고, animationData는 null로 유지되어 Lottie가 렌더링되지 않는 안전한 상태를 유지하게 변경하겠습니다!

kimminna added 3 commits July 11, 2026 02:22
- response.ok가 false일 때 에러를 throw해 에러 페이지 HTML이 animationData로 들어가지 않도록 했습니다
- 스크린 리더 사용자를 위해 로딩 Lottie에 ariaLabel을 추가했습니다
- "주새요"를 "주세요"로 수정했습니다

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
apps/timo-web/messages/ko.json (2)

46-46: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

"잠시후" 띄어쓰기가 아직 수정되지 않았습니다.

이전 리뷰에서 "잠시 후"로 수정을 제안했고 "Addressed"로 표시되었으나, 현재 코드에는 여전히 "잠시후"로 되어 있습니다. "잠시 후"는 올바른 띄어쓰기 표준입니다.

참고: 국립국어원 띄어쓰기 안내

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/timo-web/messages/ko.json` at line 46, 한국어 메시지의 description 문자열에서 잘못 붙여
쓴 “잠시후”를 표준 띄어쓰기인 “잠시 후”로 수정하세요.

51-51: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

NotFound.description에 마침표가 여전히 누락되어 있습니다.

이전 리뷰에서 마침표 추가를 제안했고 "Addressed"로 표시되었으나, 현재 코드에는 마침표가 없습니다. Error.description(Line 46)과 GlobalError.description(Line 56) 모두 마침표로 끝나므로 일관성을 위해 수정이 필요합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/timo-web/messages/ko.json` at line 51, apps/timo-web/messages/ko.json의
NotFound.description 문장 끝에 마침표를 추가해 Error.description 및 GlobalError.description과
일관되게 수정하세요.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@apps/timo-web/messages/ko.json`:
- Line 46: 한국어 메시지의 description 문자열에서 잘못 붙여 쓴 “잠시후”를 표준 띄어쓰기인 “잠시 후”로 수정하세요.
- Line 51: apps/timo-web/messages/ko.json의 NotFound.description 문장 끝에 마침표를 추가해
Error.description 및 GlobalError.description과 일관되게 수정하세요.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d506db1b-3621-4dac-a274-ee526cf23dd1

📥 Commits

Reviewing files that changed from the base of the PR and between 5ee988e and ba898b0.

📒 Files selected for processing (3)
  • apps/timo-web/app/[locale]/loading.tsx
  • apps/timo-web/components/lottie/LottiePlayer.tsx
  • apps/timo-web/messages/ko.json

@kimminna kimminna merged commit b3b20b8 into develop Jul 10, 2026
13 checks passed
@kimminna kimminna deleted the feat/web/130-status-screen-lottie branch July 10, 2026 17:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 새로운 기능(기능성) 구현 ⏰ Timo-web Timo 웹 서비스 ♦️ 민아 민아상

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 에러/로딩 상태 페이지 Lottie 애니메이션 적용

3 participants